package main;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;
import model.HostPort;
import node.NodeActual;

import registry.RemoteRegistry;
import node.Node;
import node.RemoteNode;
import node.RemoteNodeRMIEndpoint;
import node.tasks.FixFingerTable;

/**
 * Test client for registering nodes to system.
 * @author the_james_marq
 *
 */
public class CreateActualNodesTest {
    
    private static String NAME_IN_REGISTRY = RemoteNodeRMIEndpoint.NAME_IN_REGISTRY;
	/**
	 * Test client creates ten nodes.
	 * 
	 * @param args Command line arguments (hostname, port, registry name)
	 * @throws NotBoundException 
	 */
	public static void main(String[] args) throws IOException, NotBoundException {
        Registry registry = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1]));
        RemoteRegistry stub = (RemoteRegistry) registry.lookup(args[2]);
		
        //runStandardTest(stub);
		runStabilizeTest(stub);
		//runFixFingerTest(stub);
		
	}
	
	public static void runStandardTest(RemoteRegistry stub) throws RemoteException, NotBoundException {
	        
	        List<RemoteNode> testlist = new ArrayList<RemoteNode>();
	        List<NodeActual> actualnode = new ArrayList<NodeActual>();
	        for(int i=0; i<8; i++) {
	            HostPort hp = new HostPort("localhost", 8000+i*i);
	            actualnode.add(new NodeActual(stub, hp));
	            Registry registry2 = LocateRegistry.getRegistry("localhost", 8000+i*i);
	            RemoteNode stub2 = (RemoteNode) registry2.lookup(NAME_IN_REGISTRY + hp.toString());
	            testlist.add(stub2);
	            System.out.println("State of nodes after registering node ID: " + stub2.getNodeID());
	            for(RemoteNode n : testlist) {    
	                System.out.println(n.remoteToString());
	            }
	        }
	        System.out.println("test client finished.");
	        for(RemoteNode n : testlist) {  
	            System.out.println(n.remoteToString());
	           
	        }
	}
	
	public static void runStabilizeTest(RemoteRegistry stub) throws RemoteException, NotBoundException {
        List<RemoteNode> testlist = new ArrayList<RemoteNode>();
        List<NodeActual> actualnode = new ArrayList<NodeActual>();
        
        //Entries entriesOne = new Entries();
        //entriesOne.add(new Entry(0, "Hello"));
        //entriesOne.add(new Entry(3, "Good"));
        //entriesOne.add(new Entry(4, "Sir"));
        //entriesOne.add(new Entry(6, "How"));
        //entriesOne.add(new Entry(12, "are"));
        //entriesOne.add(new Entry(14, "you?"));
        //Entries entriesTwo = new Entries();
        //Entries entriesThree = new Entries();
        //Entries entriesThree = new Entries();
        HostPort hp2 = new HostPort("localhost", 8011);
        actualnode.add(new NodeActual(stub, hp2));
        Registry registry2 = LocateRegistry.getRegistry("localhost", 8011);
        RemoteNode stub2 = (RemoteNode) registry2.lookup(NAME_IN_REGISTRY + hp2.toString());
        testlist.add(stub2);
        System.out.println("State of nodes after registering node ID: " + stub2.getNodeID());
        for(RemoteNode n : testlist) {  
            System.out.println(n.remoteToString());
        }
        
        HostPort hp3 = new HostPort("localhost", 8501);
        actualnode.add(new NodeActual(stub, hp3));
        Registry registry3 = LocateRegistry.getRegistry("localhost", 8501);
        RemoteNode stub3 = (RemoteNode) registry3.lookup(NAME_IN_REGISTRY + hp3.toString());
        testlist.add(stub3);
        System.out.println("State of nodes after registering node ID: " + stub3.getNodeID());
        for(RemoteNode n : testlist) {  
            System.out.println(n.remoteToString());
        }
        
        HostPort hp4 = new HostPort("localhost", 8903);
        actualnode.add(new NodeActual(stub, hp4));
        Registry registry4 = LocateRegistry.getRegistry("localhost", 8903);
        RemoteNode stub4 = (RemoteNode) registry4.lookup(NAME_IN_REGISTRY + hp4.toString());
        testlist.add(stub4);
        System.out.println("State of nodes after registering node ID: " + stub4.getNodeID());
        for(RemoteNode n : testlist) {  
            System.out.println(n.remoteToString());
        }
        
        
	}
	
	public static void addActualNode(RemoteRegistry stub) {
        HostPort hp = new HostPort("localhost", 9555);
        new NodeActual(stub, hp);
	}
	
	public static void runFixFingerTest(RemoteRegistry stub) throws RemoteException, NotBoundException {
        List<RemoteNode> testlist = new ArrayList<RemoteNode>();
        List<NodeActual> actualnode = new ArrayList<NodeActual>();
        for(int i=0; i<4; i++) {
            HostPort hp = new HostPort("localhost", 8000+i*i);
            actualnode.add(new NodeActual(stub, hp));
            Registry registry2 = LocateRegistry.getRegistry("localhost", 8000+i*i);
            RemoteNode stub2 = (RemoteNode) registry2.lookup(NAME_IN_REGISTRY + hp.toString());
            testlist.add(stub2);
            System.out.println("State of nodes after registering node ID: " + stub2.getNodeID());
            for(RemoteNode n : testlist) {    
                System.out.println(n.remoteToString());
                   
            }
        }
        System.out.println("test client finished.");
        for(RemoteNode n : testlist) {  
            System.out.println(n.remoteToString());
           
        }
        
        for(NodeActual nod: actualnode){
            new FixFingerTable(nod, nod.getNodeReferences()).run();
            Node[] n = nod.getNodeReferences().getFingerTable().getFullFingerTable();
            System.out.println("After fixing fingertable of nodeID: "+nod.getNodeID());
            int i = 0;
            for(Node nn: n){
                System.out.println(((Math.pow(2, i) + nod.getNodeID()) % Math.pow(2, nod.getMValueOfChord())) + ": " +nn.getNodeID());
                i++;
            }
            System.out.println();
        }
	}

}
